package utils

import (
	"bufio"
	"bytes"
	"context"
	"errors"
	"fmt"
	"github.com/disintegration/imaging"
	ffmpeg_go "github.com/u2takey/ffmpeg-go"
	"onvif_server/pkg/cfgstruct"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"
)

var sysStartTime time.Time

func init() {
	sysStartTime = time.Now()
}

func IsDev() bool {
	env := cfgstruct.DefaultsType()
	return env == "" || env == "dev"
}

func GetRealTimePlayId() string {
	if runtime.GOOS == "windows" {
		return "WINDOWS_TEST"
	}
	res, err := os.ReadFile("/usr/local/bin/Guid")
	if err != nil {
		return ""
	}
	return strings.Split(string(res), "\n")[0]
}

func GetDeviceNo() string {
	if runtime.GOOS == "windows" {
		return "WINDOWS_TEST"
	}
	if IsDev() {
		return "test_device_id"
	}
	res, err := os.ReadFile("/usr/local/bin/p2puid")
	if err != nil {
		return ""
	}
	return strings.Split(string(res), "\n")[0]
}

// GetSnapshot  获取视频第几帧图片
func GetSnapshot(videoPath, snapshotFile string, frameNum int) (err error) {
	buf := bytes.NewBuffer(nil)
	err = ffmpeg_go.Input(videoPath).
		Filter("select", ffmpeg_go.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
		Output("pipe:", ffmpeg_go.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg", "s": "640*480"}).
		WithOutput(buf, os.Stdout).
		Run()
	if err != nil {
		return
	}
	img, err := imaging.Decode(buf)
	if err != nil {
		return
	}
	return imaging.Save(img, snapshotFile)
}

func FileExists(path string) (bool, error) {
	fs, err := os.Stat(path)
	if err == nil {
		if fs.IsDir() {
			return true, fmt.Errorf("path[%s] exists and is dir", path)
		}
		return true, nil
	}
	if errors.Is(err, os.ErrNotExist) {
		return false, nil
	}
	return false, err
}

func DirExists(path string) (bool, error) {
	fs, err := os.Stat(path)
	if err == nil {
		if !fs.IsDir() {
			return true, fmt.Errorf("path[%s] exists and is file", path)
		}
		return true, nil
	}
	if errors.Is(err, os.ErrNotExist) {
		return false, nil
	}
	return false, err
}

// FileReadLineString 按行读取文件，返回io.EOF 表示读完
func FileReadLineString(fileName string, fn func(line string) error) error {
	f, err := os.Open(fileName)
	if err != nil {
		return err
	}
	defer f.Close()
	buf := bufio.NewReader(f)
	var line string
	for {
		line, err = buf.ReadString('\n')
		line = strings.TrimSuffix(line, "\n")
		if err != nil {
			return err
		}
		if err = fn(line); err != nil {
			return err
		}
	}
}

// RunCmd 执行命令行
func RunCmd(ctx context.Context, cmd ...string) ([]byte, error) {
	command := exec.CommandContext(ctx, "bash", append([]string{"-c"}, cmd...)...)
	return command.CombinedOutput()
}

func GetSysRunTime() (time.Time, time.Duration) {
	return sysStartTime, time.Now().Sub(sysStartTime)
}
